/*
 *  Copyright 2009 The Apache Software Foundation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.mybatis.generator.codegen.mybatis3.model;

import java.util.ArrayList;
import java.util.List;

import org.mybatis.generator.api.CommentGenerator;
import org.mybatis.generator.api.FullyQualifiedTable;
import org.mybatis.generator.api.Plugin;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.dom.java.CompilationUnit;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.JavaVisibility;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import org.mybatis.generator.codegen.AbstractJavaGenerator;
import org.mybatis.generator.codegen.RootClassInfo;
import org.mybatis.generator.internal.util.messages.Messages;

/**
 * 
 * @author Jeff Butler
 * 
 */
public class BaseRecordGenerator extends AbstractJavaGenerator {

    public BaseRecordGenerator() {
	super();
    }

    @Override
    public List<CompilationUnit> getCompilationUnits() {
	FullyQualifiedTable table = introspectedTable.getFullyQualifiedTable();
	progressCallback.startTask(Messages.getString("Progress.8", table.toString())); //$NON-NLS-1$
	Plugin plugins = context.getPlugins();
	CommentGenerator commentGenerator = context.getCommentGenerator();

	FullyQualifiedJavaType type = new FullyQualifiedJavaType(
	        introspectedTable.getBaseRecordType());
	TopLevelClass topLevelClass = new TopLevelClass(type);
	topLevelClass.setVisibility(JavaVisibility.PUBLIC);
	commentGenerator.addJavaFileComment(topLevelClass);
	
	FullyQualifiedJavaType superClass = getSuperClass();
	if (superClass != null) {
	    topLevelClass.setSuperClass(superClass);
	    topLevelClass.addImportedType(superClass);
	}

	List<IntrospectedColumn> introspectedColumns;
	if (includePrimaryKeyColumns()) {
	    if (includeBLOBColumns()) {
		introspectedColumns = introspectedTable.getAllColumns();
	    }
	    else {
		introspectedColumns = introspectedTable.getNonBLOBColumns();
	    }
	}
	else {
	    if (includeBLOBColumns()) {
		introspectedColumns = introspectedTable
		        .getNonPrimaryKeyColumns();
	    }
	    else {
		introspectedColumns = introspectedTable.getBaseColumns();
	    }
	}

	String rootClass = getRootClass();
	for (IntrospectedColumn introspectedColumn : introspectedColumns) {
	    if (RootClassInfo.getInstance(rootClass, warnings)
		    .containsProperty(introspectedColumn)) {
		continue;
	    }

	    Field field = getJavaBeansField(introspectedColumn);
	    if (plugins.modelFieldGenerated(field, topLevelClass,
		    introspectedColumn, introspectedTable,
		    Plugin.ModelClassType.BASE_RECORD)) {
		topLevelClass.addField(field);
		topLevelClass.addImportedType(field.getType());
	    }

	    Method method = getJavaBeansGetter(introspectedColumn);
	    if (plugins.modelGetterMethodGenerated(method, topLevelClass,
		    introspectedColumn, introspectedTable,
		    Plugin.ModelClassType.BASE_RECORD)) {
		topLevelClass.addMethod(method);
	    }

	    method = getJavaBeansSetter(introspectedColumn);
	    if (plugins.modelSetterMethodGenerated(method, topLevelClass,
		    introspectedColumn, introspectedTable,
		    Plugin.ModelClassType.BASE_RECORD)) {
		topLevelClass.addMethod(method);
	    }
	}

	List<CompilationUnit> answer = new ArrayList<CompilationUnit>();
	if (context.getPlugins().modelBaseRecordClassGenerated(
	        topLevelClass, introspectedTable)) {
	    answer.add(topLevelClass);
	}
	return answer;
    }

    private FullyQualifiedJavaType getSuperClass() {
	FullyQualifiedJavaType superClass;
	if (introspectedTable.getRules().generatePrimaryKeyClass()) {
	    superClass = new FullyQualifiedJavaType(introspectedTable
		    .getPrimaryKeyType());
	}
	else {
	    String rootClass = getRootClass();
	    if (rootClass != null) {
		superClass = new FullyQualifiedJavaType(rootClass);
	    }
	    else {
		superClass = null;
	    }
	}

	return superClass;
    }

    private boolean includePrimaryKeyColumns() {
	return !introspectedTable.getRules().generatePrimaryKeyClass()
	        && introspectedTable.hasPrimaryKeyColumns();
    }

    private boolean includeBLOBColumns() {
	return !introspectedTable.getRules().generateRecordWithBLOBsClass()
	        && introspectedTable.hasBLOBColumns();
    }
}
